home *** CD-ROM | disk | FTP | other *** search
- /*
- * samall.c
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include <ctype.h>
- #include <conio.h>
- #include <time.h>
-
- #include "samapi.h"
-
- #define TRUE 1
- #define FALSE 0
- #define TIMEOUT 180
-
- /*
- * functions in samlib.c; must be passed to compiler during link phase
- */
-
- int LocateSam(void);
- int CallSam(int cmd, void far *cmdbuf, void far *rspbuf);
-
- /*
- * decls for functions contained here
- */
-
- int samc(char *, char *, char *, char *,int, char);
- void transmit_data(datarec_t *);
- int Check_BPQ(int);
- void Raise_RTS(int);
- void Lower_RTS(int);
- void Send_Break(int);
- int Write_TNC(int, char *, unsigned int);
- void Return_To_Node(int);
- int Connected(char *, int);
- int Read_TNC(int, char *);
- void Set_TNC(int, int);
- void Reset_TNC(int);
- void cru(char *);
- void Delay(int);
- void DV_Nice(void);
- int Ready(void);
-
- int port;
- int bycall = FALSE;
- int byname = FALSE;
- int oncmd = FALSE;
-
-
-
-
- int main(int argc, char *argv[])
- {
-
- char *buffer;
- char *inbuff;
- char *call;
- char *usercall;
- char *lastname;
- char *firstname;
- char *middleinitial;
- char response, initial_response;
- time_t start_time;
- time_t current_time;
- time_t user_start_time;
- time_t user_stop_time;
- char tstr[80];
-
- int appl_number;
- int i, j, l, k, m, n;
- int timedout;
-
- if (argc != 3)
- {
- fprintf(stderr, "Usage: SAMALL port appl_nmbr \n");
- exit(1);
- }
-
- /* The INT 14H port number is 1 below the commonly used port*/
- /* numbers. eg COM1: = 0, COM2: = 1 etc.*/
-
- port = atoi(argv[1]) - 1;
-
- appl_number = atoi(argv[2]);
-
- if (!Check_BPQ(port))
- exit(1);
-
- /*
- * make sure the resident code (SAMAPI.EXE)
- * has been installed
- */
-
- if (LocateSam())
- {
- printf("*** SAMAPI not loaded\n");
- exit(2);
- }
-
- Set_TNC(appl_number, port);
-
- usercall = calloc(12, sizeof(char));
-
- time(¤t_time);
- printf("version 2.50 Server started: %s", ctime(¤t_time));
-
- while (!kbhit())
- {
- if (Connected(usercall, port))
- {
- inbuff = calloc(2048, sizeof(char));
- buffer = calloc(2048, sizeof(char));
- call = calloc(10, sizeof(char));
- lastname = calloc(512, sizeof(char));
- firstname = calloc(512, sizeof(char));
- middleinitial = calloc(10, sizeof(char));
-
- n=1; j=0;
- j = Read_TNC(port, inbuff);
- for( i = 5; i <= j; i++)
- if(isalnum(inbuff[i]))
- {
- call[i-5] = inbuff[i];
- n += 1;
- }
- call[n] = '\0';
-
- if( (n < 5) || (n > 7) )
- {
- bycall = FALSE;
- byname = FALSE;
- oncmd = FALSE;
-
- Send_Break(port);
-
- strcpy(buffer, "CONV\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- time(&user_start_time);
- strcpy(tstr, ctime(&user_start_time));
- tstr[(strlen(tstr)-1)] = '\0';
-
- printf("%s on at %s", usercall, tstr);
-
- strcpy(buffer, "Welcome to the SAM database Server.");
- strcat(buffer, "\r");
- strcat(buffer, "Developed by KK4L. 15 Mar. 1992");
- strcat(buffer, "\r");
- strcat(buffer, "Inactivity timeout is set to 3 minutes.");
- strcat(buffer, "\r");
- strcat(buffer, "To avoid this menu, send the command: ");
- strcat(buffer, "\r");
- strcat(buffer, " FIND xxxxx ");
- strcat(buffer, "\r");
- strcat(buffer, "where xxxxx is the callsign of interest.");
- strcat(buffer, "\r");
- strcat(buffer, "Follow the prompts. Press enter by itself to enter a blank.");
- strcat(buffer, "\r");
- strcat(buffer, " enter: N)ame to find by name");
- strcat(buffer, " \r");
- strcat(buffer, " enter: C)all to find by callsign or");
- strcat(buffer, "\r");
- strcat(buffer, " enter: Q)uit to return to the node.");
- strcat(buffer, "\r");
- strcat(buffer, "(N, C, Q) > \r");
- Write_TNC(port, buffer, strlen(buffer));
- Read_TNC(port, buffer);
-
- timedout = FALSE;
-
- time(&start_time);
- do
- {
- j = Read_TNC(port, inbuff);
- initial_response = toupper(inbuff[0]);
- time(¤t_time);
- if((current_time - start_time) >= TIMEOUT) timedout = TRUE;
- if(initial_response == 'Q') timedout = TRUE;
- } while((initial_response != 'Q') && (timedout == FALSE)
- && (initial_response != 'N') && (initial_response != 'C'));
-
- if((timedout == FALSE) && (initial_response != 'Q'));
- {
- if(initial_response == 'N')
- {
- byname = TRUE;
- bycall = FALSE;
-
- strcpy(buffer, "Last Name ?");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- time(&start_time);
- do
- {
- j = Read_TNC(port, inbuff);
- time(¤t_time);
- if((current_time - start_time) >= TIMEOUT) timedout = TRUE;
- } while((timedout == FALSE) && (inbuff[0] == '\0'));
-
- if(timedout == FALSE)
- {
- k = 0;
- for( i = 0; i <= j; i++)
- if(isalpha(inbuff[i]))
- {
- lastname[k] = inbuff[i];
- k += 1;
- }
- lastname[k] = '\0';
-
- strcpy(buffer, "First Name ?");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- time(&start_time);
- do
- {
- j = Read_TNC(port, inbuff);
- time(¤t_time);
- if((current_time - start_time) >= TIMEOUT) timedout = TRUE;
- } while((timedout == FALSE) && (inbuff[0] == '\0'));
-
- if(timedout == FALSE)
- {
- k = 0;
- for( i = 0; i <= j; i++)
- if(isalpha(inbuff[i]))
- {
- firstname[k] = inbuff[i];
- k += 1;
- }
- firstname[k] = '\0';
-
- strcpy(buffer, "Middle Initial ?");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- time(&start_time);
- do
- {
- j = Read_TNC(port, inbuff);
- time(¤t_time);
- if((current_time - start_time) >= TIMEOUT) timedout = TRUE;
- } while((timedout == FALSE) && (inbuff[0] == '\0'));
-
- if(timedout == FALSE)
- {
- if(isalpha(inbuff[0])) middleinitial[0] = inbuff[0];
- else middleinitial[0] = '\0';
- middleinitial[1] = '\0';
- }
- }
- }
-
- strcpy(buffer, "Looking for name: ");
- Write_TNC(port, buffer, strlen(buffer));
- strcpy(buffer, lastname);
- if(strlen(lastname) > 0) strcat(buffer, ", ");
- else strcat(buffer, " ");
- strcat(buffer, firstname);
- strcat(buffer, " ");
- strcat(buffer, middleinitial);
- if(strlen(middleinitial) > 0) strcat(buffer, ".");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
- samc('\0', lastname, firstname, middleinitial, 6, 'N');
-
- }
-
- if(initial_response == 'C')
- {
- byname = FALSE;
- bycall = TRUE;
-
- strcpy(buffer, "Callsign ?");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- time(&start_time);
- do
- {
- j = Read_TNC(port, inbuff);
- time(¤t_time);
- if((current_time - start_time) >= TIMEOUT) timedout = TRUE;
- } while((timedout == FALSE) && (inbuff[0] == '\0'));
-
-
- if(timedout == FALSE)
- {
- i = 0;
- for(l = 0; l <= j; l++)
- {
- if(isalnum(inbuff[l]))
- {
- call[i++] = inbuff[l];
- }
- }
- call[i] = '\0';
- }
-
- strcpy(buffer, "Looking for callsign: ");
- Write_TNC(port, buffer, strlen(buffer));
- strcpy(buffer, call);
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
- samc(call,'\0','\0','\0', 4, 'N');
-
- }
-
- time(&start_time);
- do
- {
- j = Read_TNC(port, inbuff);
- response = toupper(inbuff[0]);
- if(response == 'N')
- {
- time(&start_time);
- if(bycall) samc("","" ,"" ,"" , 5, 'N');
- if(byname) samc("","" ,"" ,"" , 7, 'N');
- }
- if(response == 'P')
- {
- time(&start_time);
- if(bycall) samc("","" ,"" ,"" , 5, 'P');
- if(byname) samc("","" ,"" ,"" , 7, 'P');
- }
- time(¤t_time);
- if((current_time - start_time) >= TIMEOUT) timedout = TRUE;
- } while((response != 'Q') &&
- (timedout == FALSE));
- }
- }
- else
- {
- byname = FALSE;
- bycall = FALSE;
- oncmd = TRUE;
-
- Send_Break(port);
-
- strcpy(buffer, "CONV\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- time(&user_start_time);
- strcpy(tstr, ctime(&user_start_time));
- tstr[(strlen(tstr)-1)] = '\0';
-
- printf("%s on at %s using Quicklook.", usercall, tstr);
-
- samc(call,'\0','\0','\0', 4, 'N');
- }
-
- Send_Break(port);
- Read_TNC(port, inbuff);
- Delay(3);
- Return_To_Node(port);
- time(&user_stop_time);
- if(!oncmd) printf(" returned to node after %d seconds.\n", (user_stop_time - user_start_time));
- else printf(" Returned to node.\n");
-
- free(inbuff);
- free(buffer);
- free(call);
- free(lastname);
- free(firstname);
- free(middleinitial);
-
-
-
- }
- else DV_Nice();
- }
-
- Reset_TNC(port);
-
- free(usercall);
-
- return(0);
-
- }
-
- /***********************************************************************/
- /* DV_Nice - gives back ticks to DesqView */
- /***********************************************************************/
-
- void DV_Nice(void)
- {
- union REGS regs;
-
- regs.x.ax = 0x1000;
- int86(0x15, ®s, ®s);
-
- }
-
- /************************************************************************/
- /* This checks for the G8BPQ Node signiature of X'AA55' in BOTH AX and*/
- /* BX. COMBIOS and related programs only return it in AX. The version*/
- /* number is also retrieved, this could be checked if using a newly*/
- /* implemented feature of the code.*/
- /************************************************************************/
-
- int Check_BPQ(int port)
- {
- union REGS regs;
-
- regs.x.dx = port;
- regs.h.ah = 4;
-
- int86(0x14, ®s, ®s);
-
- if (regs.x.ax != 0xAA55 || regs.x.bx != 0xAA55)
- {
- fprintf(stderr, "SAMALL: G8BPQ node support not loaded\n");
- return(FALSE);
- }
-
- regs.x.dx = port;
- regs.h.ah = 0x1F;
- regs.h.al = 0;
-
- int86(0x14, ®s, ®s);
-
- return(TRUE);
- }
-
- /********************************************
- ************* Raise_RTS ******************
- ********************************************/
- void Raise_RTS(int port)
- {
- union REGS regs;
-
- regs.x.dx = port;
- regs.h.ah = 6;
-
- int86(0x14, ®s, ®s);
- }
-
- /********************************************
- ************* Lower_RTS ******************
- ********************************************/
- void Lower_RTS(int port)
- {
- union REGS regs;
- regs.x.dx = port;
- regs.h.ah = 5;
-
- int86(0x14, ®s, ®s);
- }
-
- /************************************************************************/
- /* Sending a break to the node software is the sure-fire way of getting*/
- /* back to command mode from converse and transparant mode.*/
- /************************************************************************/
-
- void Send_Break(int port)
- {
- union REGS regs;
-
- regs.x.dx = port;
- regs.h.ah = 7;
-
- int86(0x14, ®s, ®s);
- }
-
- /************************************************************************/
- /* This function takes the same sort of arguments as the C library*/
- /* function write(). It is a non blocking function that returns when*/
- /* either all of the data has been sent to the node, or when the node*/
- /* cannot accept any more data.*/
- /************************************************************************/
-
- int Write_TNC(int port, char *buf, unsigned int count)
- {
- union REGS regs;
- int attempts = 0;
- int i;
-
- for (i = 0; i < count; i++)
- {
- regs.x.dx = port;
- regs.h.ah = 3;
-
- do
- {
- attempts++;
-
- int86(0x14, ®s, ®s);
- }
- while (!(regs.h.ah & 0x20) && (attempts < 32));
-
- if (attempts == 32)
- return(i);
-
- attempts = 0;
-
- regs.x.dx = port;
- regs.h.ah = 1;
- regs.h.al = buf[i];
-
- int86(0x14, ®s, ®s);
- }
- return(i);
- }
-
- /************************************************************************/
- /* This is the gracefull way of getting rid of users, until recently the*/
- /* only available option was to disconnect them from the node, this puts*/
- /* them back to the node software.*/
- /************************************************************************/
-
- void Return_To_Node(int port)
- {
- union REGS regs;
-
- regs.x.dx = port;
- regs.h.ah = 0x1F;
- regs.h.al = 0x10;
-
- int86(0x14, ®s, ®s);
- }
-
- /************************************************************************/
- /* This function serves two purposes, it indicates whether the*/
- /* application is connected to a user, and if so, what their callsign*/
- /* is. At present it does not return the users ssid, but it is available*/
- /* if needed. The code gets the users callsign from the INT 14H and not*/
- /* from parsing the "*** CONNECTED to ..." line. This piece of the code*/
- /* makes use of a far pointer to the callsign within the Node software.*/
- /* It then has to be converted to ASCII from AX25 format, which is*/
- /* essentially shifting the characters right by one bit.*/
- /************************************************************************/
-
- int Connected(char *buff, int port)
- {
- union REGS regs;
- struct SREGS segregs;
- unsigned char far *calls;
- int i;
-
- regs.x.dx = port;
- regs.h.ah = 0x1F;
- regs.h.al = 1;
-
- int86x(0x14, ®s, ®s, &segregs);
-
- if (regs.x.si == 0)
- return(FALSE);
-
- calls = MK_FP(segregs.es,regs.x.si);
-
- for (i = 0; (calls[i] >> 1) != ' ' && i < 6; i++)
- buff[i] = calls[i] >> 1;
-
- buff[i] = '\0';
-
- return(TRUE);
- }
-
-
- /************************************************************************/
- /* This routine is a non-blocking read of the port input stream.*/
- /************************************************************************/
-
- int Read_TNC(int port, char *buffer)
- {
- union REGS regs;
- int i;
-
- regs.x.dx = port;
- regs.h.ah = 3;
-
- int86(0x14, ®s, ®s);
-
- i = 0;
-
- while (regs.h.ah & 0x01)
- {
- regs.x.dx = port;
- regs.h.ah = 2;
-
- int86(0x14, ®s, ®s);
-
- buffer[i++] = regs.h.al;
-
- regs.x.dx = port;
- regs.h.ah = 3;
-
- int86(0x14, ®s, ®s);
- }
-
- buffer[i] = '\0';
-
- return(i);
- }
-
- /********************************************
- ************* Set_TNC ********************
- ********************************************/
- void Set_TNC(int appl_number, int port)
- {
- char *command;
- char *buff;
-
- Raise_RTS(port);
-
- Send_Break(port);
-
- buff = calloc(1024, sizeof(char));
- command = calloc(80, sizeof(char));
-
- command = "ECHO OFF\r";
- Write_TNC(port, command, strlen(command));
- Read_TNC(port, buff);
-
- sprintf(buff, "APPL $%02X\r", appl_number);
- Write_TNC(port, buff, strlen(buff));
- Read_TNC(port, buff);
-
- command = "MONITOR OFF\r";
- Write_TNC(port, command, strlen(command));
- Read_TNC(port, buff);
-
- command = "CONOK ON\r";
- Write_TNC(port, command, strlen(command));
- Read_TNC(port, buff);
-
- free(buff);
- free(command);
-
- }
-
-
- /********************************************
- ************* Reset_TNC ******************
- ********************************************/
- void Reset_TNC(int port)
- {
- char *command;
- char *buff;
-
- Send_Break(port);
-
- buff = calloc(1024, sizeof(char));
- command = calloc(80, sizeof(char));
-
- command = "APPL $00\r";
- Write_TNC(port, command, strlen(command));
- Read_TNC(port, buff);
-
- command = "CONOK OFF\r";
- Write_TNC(port, command, strlen(command));
- Read_TNC(port, buff);
-
- Lower_RTS(port);
-
- free(buff);
- free(command);
-
- }
-
- /************************************************************************/
- /* This function takes its name from a UNIX utility at Nottingham Uni*/
- /* called Carriage Return Utility. It converts between the carriage*/
- /* returns standards found on packet radio to the standards used in DOS*/
- /************************************************************************/
-
- void cru(char *string)
- {
- int i;
-
- for (i = 0; string[i] != '\0'; i++)
- {
- switch (string[i])
- {
- case '\r':
- string[i] = '\n';
- break;
- case '\n':
- string[i] = '\r';
- break;
- }
- }
- }
-
-
- /************************************************************************/
- /* Delay for n seconds. In a "real" piece of software, it would be wise*/
- /* to give time slices to DESQview at the point. The same can also be*/
- /* said of the loop in main() where it is waiting for a user.*/
- /************************************************************************/
-
- void Delay(int delay)
- {
- time_t start_time;
- time_t current_time;
-
- time(&start_time);
-
- do
- {
- DV_Nice();
- time(¤t_time);
- }
- while ((current_time - start_time) < delay);
- }
-
-
- /**********************************************************************/
- /* SAM supplied lookup routines for callsign lookup without scroll ***/
- /**********************************************************************/
-
- int samc(char *callin, char *lastnamein, char *firstnamein, char *middleinitialin, int func, char updwn)
- {
- char *buffer;
- cmdfindname_t sam_name_in;
- cmdgetrecs_t sam_next;
- cmdfindcall_t sam_in;
- rspdatarec_t sam_out;
- int err;
-
- /*
- * No un-assigned pointers here!
- */
-
- buffer = calloc(1024, sizeof(char));
-
- /*
- * build command block and call SAMAPI, function SamFindCall
- */
- if(func == 4)
- {
- sam_in.packflags = 0; /* 0 to unpack all data record fields */
- strncpy(sam_in.call, callin, 6);
- sam_in.call[6] = 0;
- err = CallSam(SamFindCall, &sam_in, &sam_out);
- if (err == SerrNotFound)
- {
- if(!oncmd) strcpy(buffer, "Not found but the closest call is:");
- else {
- strncpy(buffer, callin, strlen(callin));
- strcat(buffer, " not found ...");
- }
-
- strcat(buffer, "\r");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
- }
- /*
- * check for unusual error
- * something other that plain ole not found
- */
-
- if (err != 0 && err != SerrNotFound)
- {
-
- strcpy(buffer, "*** SAMAPI error ");
- strcat(buffer, "\r");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- return(2);
- }
- }
-
- if(func == 5)
- {
- sam_next.packflags = 0; /* 0 to unpack all data record fields */
- if(updwn == 'N') sam_next.index = sam_out.d.Cindex + 1;
- if(updwn == 'P') sam_next.index = sam_out.d.Cindex - 1;
- err = CallSam(SamGetRecordByCall, &sam_next, &sam_out);
- /*
- * check for unusual error
- * something other that plain ole not found
- */
-
- if (err != 0 && err != SerrNotFound)
- {
-
- strcpy(buffer, "*** SAMAPI error ");
- strcat(buffer, "\r");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- return(2);
- }
- }
- /*
- * build command block and call SAMAPI, function SamFindName
- */
- if(func == 6)
- {
- sam_name_in.packflags = 0; /* 0 to unpack all data record fields */
- strncpy(sam_name_in.lastname, lastnamein, 20);
- strncpy(sam_name_in.firstname, firstnamein, 10);
- strncpy(sam_name_in.midinitial, middleinitialin, 1);
- err = CallSam(SamFindName, &sam_name_in, &sam_out);
- if (err == SerrNotFound)
- {
- strcpy(buffer, "Not found but the closest entry is:");
- strcat(buffer, "\r");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
- }
- /*
- * check for unusual error
- * something other that plain ole not found
- */
-
- if (err != 0 && err != SerrNotFound)
- {
-
- strcpy(buffer, "*** SAMAPI error ");
-
- strcat(buffer, "\r");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
- return(2);
- }
- }
-
- if(func == 7)
- {
- sam_next.packflags = 0; /* 0 to unpack all data record fields */
- if(updwn == 'N') sam_next.index = sam_out.d.Nindex + 1;
- if(updwn == 'P') sam_next.index = sam_out.d.Nindex - 1;
- err = CallSam(SamGetRecordByName, &sam_next, &sam_out);
- /*
- * check for unusual error
- * something other that plain ole not found
- */
-
- if (err != 0 && err != SerrNotFound)
- {
-
- strcpy(buffer, "*** SAMAPI error ");
-
- strcat(buffer, "\r");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
-
- return(2);
- }
- }
-
-
- /*
- * got a match, display the call data
- */
-
- if(!oncmd)
- {
- transmit_data(&sam_out.d);
- strcpy(buffer, "enter: N)ext, P)revious or Q)uit");
- strcat(buffer, "\r");
- strcat(buffer, "\r");
- strcat(buffer, "(N, P, Q) >");
- strcat(buffer, "\r");
- Write_TNC(port, buffer, strlen(buffer));
- }
- else
- if(err != SerrNotFound) transmit_data(&sam_out.d);
-
- /*
- * exit with 0 for success
- */
- free(buffer);
- return 0;
- }
-
- /*******************
- * transmit_data
- *******************
- *
- * transmits data out the port formatted:
- * first [m ]last callsign
- * address
- * city, st zip
- * class year born
- *
- * input is pointer to data record
- *
- * returns nothing
- */
-
- void transmit_data(datarec_t *d)
- {
- char *buff;
-
- buff = calloc(1024, sizeof(char));
-
- strcpy(buff, d->FirstName);
- strcat(buff, " ");
- if (d->MidInitial[0] != ' ')
- {
- strcat(buff, d->MidInitial);
- strcat(buff, " ");
- }
- strcat(buff, d->LastName);
- strcat(buff, " --- ");
- strcat(buff, d->Call + (d->Call[0] == ' '));
- strcat(buff, "\r");
- strcat(buff, d->Address);
- strcat(buff,"\r");
- Write_TNC(port, buff, strlen(buff));
- strcpy(buff, d->City);
- strcat(buff, ", ");
- strcat(buff, d->State);
- strcat(buff, " ");
- strcat(buff, d->Zip);
- strcat(buff, "\r");
- strcat(buff, "License Class: ");
- strcat(buff, d->Class);
- strcat(buff, " Year Born: 19");
- strcat(buff, d->Dob);
- strcat(buff, "\r");
- strcat(buff, "\r");
- Write_TNC(port, buff, strlen(buff));
- free(buff);
- }
-